package com.shengqiang.zhenhuiTransfer.utils;

import com.google.common.base.Strings;
import com.google.common.collect.Lists;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.DefaultHttpRequestRetryHandler;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;

/**
 * Created by eward on 2017/9/14.
 */
public class HttpClientUtil {
    private static Logger LOGGER = LoggerFactory.getLogger(HttpClientUtil.class);

    private static int socketTimeout = 10000;
    private static int connectTimeout = 10000;
    private static int connectionRequestTimeout = 10000;
    private static int maxTotal = 2000;

    private static PoolingHttpClientConnectionManager cm = null;
    private static RequestConfig requestConfig;

    static {
        LayeredConnectionSocketFactory sslsf = null;
        try {
            sslsf = new SSLConnectionSocketFactory(SSLContext.getDefault());
        } catch (NoSuchAlgorithmException e) {
            LOGGER.error("创建SSL连接失败");
        }
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("https", sslsf)
                .register("http", new PlainConnectionSocketFactory())
                .build();
        cm =new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        cm.setMaxTotal(maxTotal);
        cm.setDefaultMaxPerRoute(maxTotal);

        requestConfig = RequestConfig.custom()
                .setConnectionRequestTimeout(connectionRequestTimeout)
                .setSocketTimeout(socketTimeout)
                .setConnectTimeout(connectTimeout).build();
    }

    /**
     * 获取http连接
     * @return
     */
    private static CloseableHttpClient getHttpClient() {
            CloseableHttpClient httpClient = HttpClients.custom()
                // 设置连接池管理
                .setConnectionManager(cm)
                // 设置请求配置
                .setDefaultRequestConfig(requestConfig)
                // 设置重试次数
                .setRetryHandler(new DefaultHttpRequestRetryHandler(0, false))
                .build();
        if (cm != null && cm.getTotalStats() != null) {
            LOGGER.info("now client pool " + cm.getTotalStats().toString());
        }
        return httpClient;
    }

    /**
     * http get请求
     * @param url
     * @return
     */
    public static String httpGet(String url) {
        try {
            HttpGet httpget = new HttpGet(url);
            ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
                @Override
                public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException {
                    int status = response.getStatusLine().getStatusCode();
                    if (status >= 200 && status < 300) {
                        HttpEntity entity = response.getEntity();
                        return entity != null ? EntityUtils.toString(entity) : null;
                    } else {
                        throw new ClientProtocolException("http get response status: " + status);
                    }
                }
            };
            return  getHttpClient().execute(httpget, responseHandler);
        } catch(Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    /**
     * http get请求
     * @param url
     * @return
     */
    public static String httpGet(String url, Map<String,String> headerParams) {
        try {
            HttpGet httpget = new HttpGet(url);
            //构建header的参数
            if (headerParams != null && headerParams.size() > 0 ) {
                Header[] headers =  buildHeader(headerParams);
                httpget.setHeaders(headers);
            }
            ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
                @Override
                public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException {
                    int status = response.getStatusLine().getStatusCode();
                    if (status >= 200 && status < 300) {
                        HttpEntity entity = response.getEntity();
                        return entity != null ? EntityUtils.toString(entity) : null;
                    } else {
                        throw new ClientProtocolException("http get response status: " + status);
                    }
                }
            };
            return  getHttpClient().execute(httpget, responseHandler);
        } catch(Exception ex) {
            ex.printStackTrace();
            return null;
        }
    }

    /**
     * http post 请求
     * @param url
     * @param bodyParams
     * @param charset
     * @return
     */
    public static String httpPost(String url, String bodyParams , Map<String,String> headerParams, String charset, boolean isSSL) {
        if (Strings.isNullOrEmpty(url)) {
            return null;
        }
        try {
            HttpPost httpPost = new HttpPost(url);
            //构建header的参数
            if (headerParams != null && headerParams.size() > 0 ) {
                Header[] headers =  buildHeader(headerParams);
                httpPost.setHeaders(headers);
            }
            if (!Strings.isNullOrEmpty(bodyParams)) {
                StringEntity entity = new StringEntity(bodyParams, charset);
                httpPost.setEntity(entity);
            }
            ResponseHandler<String> responseHandler = new ResponseHandler<String>() {
                @Override
                public String handleResponse(final HttpResponse response) throws ClientProtocolException, IOException {
                    int status = response.getStatusLine().getStatusCode();
                    if (status >= 200 && status < 300) {
                        HttpEntity entity = response.getEntity();
                        return entity != null ? EntityUtils.toString(entity) : null;
                    } else {
                        throw new ClientProtocolException("http post response status: " + status);
                    }
                }
            };
            return  getHttpClient().execute(httpPost, responseHandler);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 构建POST请求BODY参数
     * @param params
     * @return
     */
    private static List<NameValuePair> buildPair(Map<String, Object> params) {
        List<NameValuePair> pairs = Lists.newArrayList();
        if (null != params && !params.isEmpty()) {
            for (Map.Entry<String, Object> entry : params.entrySet()) {
                if (!Strings.isNullOrEmpty(entry.getKey()) && entry.getValue() != null) {
                    pairs.add(new BasicNameValuePair(entry.getKey(), String.valueOf(entry.getValue())));
                }
            }
        }
        return pairs;
    }

    /**
     * 构建POST请求HEAD参数
     * @param headerMap
     * @return
     */
    private static Header[] buildHeader(Map<String, String> headerMap) {
        Header[] headers = new Header[headerMap.size()];
        int count = 0;
        for (Map.Entry<String, String> entry : headerMap.entrySet()) {
            Header header = new BasicHeader(entry.getKey(),entry.getValue());
            headers[count] = header;
            count++;
        }
        return headers;
    }
}
